<!-- ButtonScroller.vue -->
<template>
  <div class="scroll-container" :style="containerStyle" ref="containerRef">
    <div class="button-wrapper" ref="wrapperRef" :style="wrapperStyle">
      <button
        v-for="(text, index) in displayButtons"
        :key="index"
        class="scroll-button"
        @click="handleClick(text)"
      >
        {{ text.template }}
      </button>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'

const props = defineProps({
  width: {
    type: [String, Number],
    default: '100%',
  },
  buttons: {
    type: Array,
    required: true,
  },
})

// 定义事件
const emit = defineEmits(['click'])

const containerRef = ref(null)
const wrapperRef = ref(null)
const needScroll = ref(false)
const position = ref(0)

// 容器样式
const containerStyle = computed(() => ({
  width: typeof props.width === 'number' ? `${props.width}px` : props.width,
}))

// 显示的按钮列表
const displayButtons = computed(() =>
  needScroll.value
    ? [...props.buttons, ...props.buttons, ...props.buttons]
    : props.buttons,
)

// wrapper样式
const wrapperStyle = computed(() => ({
  transform: needScroll.value ? `translateX(${position.value}px)` : '',
  position: needScroll.value ? 'absolute' : 'static',
  justifyContent: needScroll.value ? 'flex-start' : 'center',
}))

let animationId = null
let paused = false
let resizeObserver = null

// 按钮点击处理
const handleClick = (text) => {
  emit('click', text)
}

// 停止动画
const stopAnimation = () => {
  if (animationId) {
    cancelAnimationFrame(animationId)
    animationId = null
  }
}

// 完全重置状态
const resetState = () => {
  stopAnimation()
  position.value = 0
  needScroll.value = false
  paused = false
}

// 检查是否需要滚动
const checkNeedScroll = async () => {
  if (!wrapperRef.value || !containerRef.value) return

  resetState()
  await nextTick()

  const containerWidth = containerRef.value.offsetWidth
  const singleGroupWidth =
    wrapperRef.value.scrollWidth / (needScroll.value ? 3 : 1)

  needScroll.value = singleGroupWidth > containerWidth

  if (needScroll.value) {
    await nextTick()
    startScroll()
  }
}

// 开始滚动
const startScroll = () => {
  const animate = () => {
    if (!needScroll.value || paused) {
      animationId = requestAnimationFrame(animate)
      return
    }

    position.value -= 0.2

    if (!wrapperRef.value) return

    const groupWidth = wrapperRef.value.scrollWidth / 3

    if (Math.abs(position.value) >= groupWidth * 2) {
      position.value += groupWidth
    }

    animationId = requestAnimationFrame(animate)
  }

  animationId = requestAnimationFrame(animate)
}

// 监听属性变化
watch(
  [() => props.width, () => props.buttons],
  async () => {
    await nextTick()
    checkNeedScroll()
  },
  { deep: true },
)

// 生命周期钩子
onMounted(() => {
  resizeObserver = new ResizeObserver(() => {
    checkNeedScroll()
  })

  if (containerRef.value) {
    resizeObserver.observe(containerRef.value)
  }

  checkNeedScroll()

  wrapperRef.value?.addEventListener('mouseenter', () => {
    paused = true
  })

  wrapperRef.value?.addEventListener('mouseleave', () => {
    paused = false
  })
})

onUnmounted(() => {
  resetState()
  if (resizeObserver) {
    resizeObserver.disconnect()
  }
})
</script>

<style scoped>
.scroll-container {
  height: 60px;
  border-radius: 10px;
  overflow: hidden;
  position: relative;
  /* margin: 20px auto; */
  max-width: 800px;
}

.button-wrapper {
  display: flex;
  gap: 10px;
  padding: 10px;
  height: 100%;
  align-items: center;
}

.scroll-button {
  flex-shrink: 0;
  padding: 8px 16px;
  background: #fafafa;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  /* border: 1px solid #e6e8eb; */
  border-radius: 6px;
  color: #aaa;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.3s ease;
  font-size: 12px;
  border: none;
}

.scroll-button:hover {
  /* background: #e6e8eb; */
  background: var(--el-color-primary-light-9);
  color: var(--el-color-primary);
  /* background: #eeedff;
  color: #615ced; */
  transform: translateY(-2px);
}
</style>
